package eerbaar.shared.persist.node;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import eerbaar.shared.persist.IPersistService;
import eerbaar.shared.persist.IPersister;
import eerbaar.shared.persist.ISaver;
import eerbaar.shared.service.ServiceFactory;
import eerbaar.shared.tree.IAttribute;
import eerbaar.shared.tree.IAttributes;
import eerbaar.shared.tree.INode;
import eerbaar.shared.tree.NodeFactory;

public class NodePersister implements IPersister<INode> {

    private INode target;

    public NodePersister() {
        //
    }

    public NodePersister(INode node) {
        this.target = node;
    }

    @Override
    public Class<INode> getRegistertedInterface() {
        return INode.class;
    }

    @Override
    public ISaver<INode>[] getSavableChildren() {

        List<NodePersister> result = new ArrayList<NodePersister>();
        INode[] children = this.target.getChildren();
        for (INode n : children) {
            result.add(new NodePersister(n));
        }
        return result.toArray(new NodePersister[] {});
    }

    @Override
    public String getSavableName() {
        return "node";
    }

    @Override
    public INode getTarget() {
        return this.target;
    }

    @Override
    public boolean isAssignableFrom(ISaver<?> savable) {
        return false;
    }

    @Override
    public INode load(INode node) {

        IPersistService service = ServiceFactory
                .getService(IPersistService.class);
        IPersister<INode> p = service.getPersister(INode.class);

        INode result;
        String key = node.getAttributes().get(String.class, "key");
        String value = node.getAttributes().get(String.class, "value");
        if (value == null) {
            result = NodeFactory.create(key);
        } else {
            result = NodeFactory.create(key, value);
        }

        Iterator<IAttribute<Object>> i = node.getAttributes().iterator();
        while (i.hasNext()) {

            IAttribute<java.lang.Object> a = i.next();

            String k = a.getKey();
            if (k.equals("key") || k.equals("value")) {
                continue;
            }

            String v = a.getValue().toString();
            result.getAttributes().set(String.class, k, v);
        }

        INode[] children = node.getChildren();
        for (INode child : children) {
            INode loaded = p.load(child);
            result.add(loaded);
        }

        return result;
    }

    @Override
    public void saveAttributes(INode node) {
        IAttributes attributes = this.target.getAttributes();

        String name = this.target.getPayload().getKey();
        node.getAttributes().set(String.class, "key", name);

        for (IAttribute<?> a : attributes) {
            String key = a.getKey();
            Object value = a.getValue();
            node.getAttributes().set(Object.class, key, value);
        }
        savePayload(node);
    }

    private void savePayload(INode node) {
        if (this.target.getPayload().getValue().length() > 0) {
            node.getAttributes().set(String.class, "value",
                    this.target.getPayload().getValue());
        }
    }

    @Override
    public void setTarget(INode obj) {
        throw new UnsupportedOperationException();
    }

}
